package cn.cnysa.spider.logic;

import cn.cnysa.spider.data.OrmFlag;
import cn.cnysa.spider.data.Property;
import cn.cnysa.spider.util.HttpUtil;
import cn.cnysa.spider.util.Log;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author Memory_Leak
 *         Created by ireal on 15-7-8.
 */
public class Pager implements Cloneable {
    private String url = null;
    private String items = null;
    private String next = null;
    private Map<String, String> ormProperties = null;
    private String clazz = null;
    private Document document = null;

    private Pager() {
    }

    public boolean hasNext() {
        Elements elements = document.select(next);
        if (elements.size() <= 0)
            return false;
        return elements.first().attr("href") == null;
    }

    public Pager next() {
        if (next == null && !hasNext())
            return null;
        Pager pager = clone();
        pager.url = document.select(next).first().attr("href");
        System.out.println("next_page:\t" + pager.url);
        return pager;
    }

    /**
     * 加载当前页面
     */

    public void prepared() throws IOException {
        document = HttpUtil.doGet(url);
        System.out.println(document.text());
    }

    /**
     * 复制当前对象
     */
    @Override
    protected Pager clone() {
        Builder builder = new Builder();
        Pager pager = builder.items(items).next(next).url(url).clazz(clazz).build();
        pager.ormProperties = ormProperties;
        return pager;
    }

    /**
     * 使用默认的Class注入对象
     */
    public List<Object> items() {
        try {
            Class c = Class.forName(clazz);
            return items(c);
        } catch (Exception e) {
            Log.e("Pager->items", e);
        }
        return null;
    }

    /**
     * 使用反射把html页面解析为对象
     */
    public <T> List<T> items(Class<T> clazz) {
        Iterator<String> iterator = loadList(document).iterator();
        List<T> list = new ArrayList<T>();
        while (iterator.hasNext()) {
            String link = iterator.next();
            try {
                Document document = HttpUtil.doGet(link);
                T t = item(document, clazz);
                if (t != null)
                    list.add(t);
            } catch (Exception e) {
                Log.w("Pager->items", e);
                continue;
            }
        }
        return list;
    }

    private <T> T item(Document document, Class<T> clazz) {
        Method[] methods = clazz.getMethods();
        try {
            T t = clazz.newInstance();
            for (Method m : methods) {
                if (!m.isAnnotationPresent(OrmFlag.class))
                    continue;
                OrmFlag flag = m.getAnnotation(OrmFlag.class);
                if (!ormProperties.containsKey(flag.value())) {
                    continue;
                }
                String sel = ormProperties.get(flag.value());
                String text = document.select(sel).text();
                m.invoke(t, text);
            }
            return t;
        } catch (Exception e) {
            Log.w(e);
            return null;
        }
    }

    /**
     * 加载当前页面的链接列表
     */
    private List<String> loadList(Document document) {
        Elements elements = document.select(items);
        Iterator<Element> iterator = elements.iterator();
        List<String> linkList = new ArrayList<String>();
        while (iterator.hasNext()) {
            Element element = iterator.next();
            String href = element.attr("href");
            if (href != null)
                linkList.add(href);
        }
        return linkList;
    }

    public static class Builder {
        private Pager pager = new Pager();

        public Builder() {
        }

        public Pager build() {
            return pager;
        }

        public Builder url(String url) {
            pager.url = url;
            return this;
        }

        public Builder items(String selector) {
            pager.items = selector;
            return this;
        }

        public Builder next(String next) {
            pager.next = next;
            return this;
        }

        public Builder clazz(String clazz) {
            pager.clazz = clazz;
            return this;
        }

        public Builder orm(Property property) {
            if (pager.ormProperties == null)
                pager.ormProperties = new HashMap<String, String>();
            pager.ormProperties.put(property.getKey(), property.getValue());
            return this;
        }
    }
}